home *** CD-ROM | disk | FTP | other *** search
/ Gekkan Dennou Club 147 / Gekkan Dennou Club - 2000.8 Vol. 147 (Japan).7z / Gekkan Dennou Club - 2000.8 Vol. 147 (Japan) (Track 1).bin / fdimg / —‹Œêsrc.lzh / work.c < prev    next >
C/C++ Source or Header  |  1993-03-18  |  29KB  |  1,195 lines

  1. #include    "3DDEF.H"
  2. #include    "GLOBAL.H"
  3. #include    "FORWARD.H"
  4. #include    "XCODE.H"
  5.  
  6. extern UWORD CRX,CRY;
  7.  
  8. /* エディタのコア */
  9. void
  10. work()
  11. {
  12.     if (DUM_FLAG) {
  13.         fep_hmode_set((UBYTE)'M');
  14.         disp_hmode();        /* 一番下の行に変換モード表示を行う */
  15.     }
  16.  
  17.     work_line_analyze();        /* 行の解析 */
  18.     CX = CX0 = CY = CPX = 0;    /* 現在のカーソル位置(相対) */
  19.     work_cursor_cpx();
  20.  
  21.     while(1) {
  22.         commander();
  23.     }
  24. }
  25.  
  26. UBYTE l[VERY_LONG_LINE*8], s[VERY_LONG_LINE*8], w[VERY_LONG_LINE*8];    /* 十分なエリア */
  27.  
  28. /* 現在のカーソル位置に文字列を挿入する:エコーする */
  29. /* あまり凶悪に長いのはだめよ */
  30. void
  31. work_insert_str(STR s)
  32. {
  33.     int len;
  34.     register int i;
  35.  
  36.     len = strlen(s);
  37.     line_cl_strncpy(l,i = ANALYZE[CPX].BPOS);    /* ok */
  38.     l[i] = EOS;
  39.     strcat(l,s);
  40.     line_cl_strcat(l,i);                /* ok */
  41.     work_cl_replace_plus(i+len);
  42. }
  43.  
  44. /* 現在行の指定区間を削除する */
  45. /* フラグにより、バッファに入れる */
  46. void
  47. work_delete_cl_between(int b1,int b2,int flag)
  48. {
  49.     UNIT *wp,*wp0;
  50.  
  51.     line_seigyou();
  52.     line_get_body(l,CL);
  53.     work_delete_between(CL,b1,b2,flag);
  54.     line_get_body(l,CL);
  55.     if (string_disp_len(l)) {    /* まだ実体が残っている */
  56.         if (CL->ATO == TAIL) {
  57.             register int y;
  58.  
  59.             line_store_and_echo(CL,l);
  60. /* CL の b1 に行く */
  61.             for(y = CY+1;y <= (CWY1-CWY0);y++) {
  62.                 disp_half_line_rel(0,y,(STR) "");
  63.             }
  64. /*            work_cl_replace_plus(b1);*/
  65.             return;
  66.         }
  67. /*        line_cat_body(l,CL->ATO);*/
  68. /*        line_delete1_echo_after_bag(CL->ATO);*/
  69. /*        line_delete1(CL->ATO);*/
  70. /*        line_deleten_SCREEN(CL,(CL->ATO)->ATO);*/
  71.         work_cl_replace_plus(b1);
  72.     } else {
  73.         if ((wp0 = CL->ATO) != TAIL) {
  74.             if (*l) {    /* マークなどが残っている */
  75.                 line_cat_body(l,wp0);
  76.                 line_store_and_echo(wp0,l);    /* こっそり前に付け足す */
  77.             }
  78.             line_delete1_echo_after_bag(CL);    /* CL を削除する */
  79.             CL = wp0;    /* 後ろに行く */
  80.             if ((CY = window_is_this_line_in_current(CL)) < 0) {
  81.                 disp_cl_center();
  82.             }
  83.         } else {    /* 0行になった */
  84.             disp_1line(CY,CL);
  85.             disp_check_1line_echo(CL);
  86.         }
  87.         line_cl_cl();
  88.         work_line_analyze();
  89.         CX0 = CPX = 0;    /* 行頭へ */
  90.     }
  91. }
  92.  
  93. /* 一行の2点間を削除し、フラグによりカットバッファに入れる */
  94. /* 削除した中にマークがあったなら、削除の後ろにつめる:うう、最後が EOS きっと大丈夫 */
  95. /* ユニットへのポインタと、バイト位置を与える */
  96. /* b1 <= 削除 < b2 */
  97. /* エコーしない */
  98. void
  99. work_delete_between(UNIT *p,int b1,int b2,int flag)
  100. {
  101.     register int i;
  102.     UINT mask;
  103.  
  104.     line_get_body(w,p);        /* w に取り出す */
  105.     strncpy(l,w,i = b1);        /* l に前を入れる */
  106.     strncpy(s,&w[b1],b2-b1);    /* s に削除部分を入れる */
  107.     s[b2-b1] = EOS;
  108.     if (flag) {
  109.         mask = buff_add_to_cut_buff(s);
  110.     } else {
  111.         mask = mark_find_mark(s);
  112.     }
  113.     if (mask) {    /* 削除した中にマークがあった */
  114.         register UINT m = 1,bc = 0;
  115.         for(;mask;m <<= 1,bc++) {
  116.             if (mask & m) {
  117.                 mask ^= m;    /* ビットを倒す */
  118.                 l[i++] = XCODE_UP;
  119.                 l[i++] = XCODE_MARK + bc;
  120.             }
  121.         }
  122.     }
  123.     l[i] = EOS;
  124.     strcat(l,&w[b2]);    /* 後ろ部分を接続 */
  125.     line_store(p,l);    /* エコーしない */
  126. }
  127.  
  128. /* 現在のカーソル位置の1文字(1、2バイトコード)を削除する:エコーする */
  129. /* バッファには入れない */
  130. void
  131. work_delete1char()
  132. {
  133.     int b1,b2;
  134.  
  135.     b1 = ANALYZE[CPX].BPOS;
  136.     b2 = ANALYZE[CPX+1].BPOS;
  137.     work_delete_cl_between(b1,b2,0);
  138. }
  139.  
  140. /* CLの次の行の先頭の1文字を削除する */
  141. /* エコーする */
  142. void
  143. work_delete1char_special()
  144. {
  145.     register int i;
  146.     UBYTE w0[VERY_LONG_LINE];
  147.     STR p;
  148.  
  149.     line_get_body(w0,CL->ATO);
  150.     p = line_skip_xcode(w0);    /* 拡張コードをスキップする */
  151.     i = string_1or2_byte_code(*p);
  152.     strcpy(l,&p[i]);
  153.     work_xl_replace_minus(CL->ATO,CY+1);
  154. }
  155.  
  156. /* 現在行を l に置き換える。画面全体にエコーする */
  157. /* l は現在行(CL_DATA)よりも長くなくてはいけない */
  158. /* bx はカーソルのあるべきバイト位置 */
  159. /* 禁則処理の関係で、前の行へ送り込まれたら非零を返す */
  160. int
  161. work_cl_replace_plus(register int bx)
  162. {
  163.     UBYTE wl[VERY_LONG_LINE];
  164.     int bb,ll,kflag;
  165.     UNIT *cl0;
  166.  
  167.     cl0 = CL;    /* トレースし直す時のために保存しておく */
  168.     if (kflag = work_cl_replace_minus()) {
  169.         bx += kflag;
  170.         if (bx < 0) {    /* カーソルは前の行に移動する */
  171.             cl0 = CL = CL->MAE;    /* cl0 が無くなっている可能性がある */
  172.             bx += CL->LENGTH;
  173.             bb = bx;
  174.         } else {    /* カーソルは CL の上にある */
  175.             bb = 0;
  176.             if (!bx && (kflag < 0)) {    /* 前の行に送られ、自分は行頭にいる */
  177.                 if (CL == TAIL) {
  178.                     UNIT *wp;
  179.                     /* 前の行は一行で完結しており、CL はその先にある */
  180.                     wp = line_get_free_and_store("");
  181.                     line_append1_echo(wp);
  182.                     CL = line_trace_byte(wp,0,bx,&bb,&ll);
  183.                 }
  184.             } else {
  185.                 CL = line_trace_byte(CL,0,bx,&bb,&ll);
  186.             }
  187.         }
  188.     } else {    /* 禁則処理にともなう出し入れは無かった */
  189.         CL = line_trace_byte(CL,0,bx,&bb,&ll);
  190.     }
  191.  
  192.     if ((CY = window_is_this_line_in_current(CL)) < 0) {
  193.         line_seigyou();
  194.         CL = line_trace_byte(cl0,0,bx,&bb,&ll);    /* トレースし直す */
  195.         
  196.         if (CMDMOD) {    /* ED モードである */
  197.             if (ll > 0) {    /* 後ろへ動いた */
  198.                 disp_cl_y(CWY1);
  199.             } else {
  200.                 disp_cl_y(CWY0);
  201.             }
  202.         } else {    /* ME モードである */
  203.             disp_cl_center();
  204.         }
  205.     }
  206.     line_cl_cl();
  207.     work_line_analyze();
  208.     CPX = work_byte_to_CPX(bb);
  209.     CX0 = CX = ANALYZE[CPX].XPOS;
  210.     if (CPX && (line_cl_1byte(CPX-1) == CR)) {    /* 左が改行 */
  211.         line_seigyou();
  212.         if (CL->ATO == TAIL) {
  213.             ctrl_b();
  214.         } else {
  215.             ctrl_f();
  216.         }
  217.     }
  218.     work_cursor_cpx();
  219. }
  220.  
  221. /* 現在行を l に置き換える。画面全体にエコーする */
  222. /* 禁則処理の関係で、前の行へ送り込まれたら非零を返す */
  223. int
  224. work_cl_replace_minus()
  225. {
  226.     return(work_xl_replace_minus(CL,CY));
  227. }
  228.  
  229. /* 指定された行を l に置き換える。画面全体にエコーする */
  230. /* y は行座標 */
  231. /* 禁則処理の関係で、前の行へ送り込まれたら非零を返す */
  232. /* 前の行に何バイト送り込まれたかを返す */
  233. int
  234. work_xl_replace_minus(UNIT *xl,int y)
  235. {
  236.     int flag,kflag = 0;
  237.     UBYTE w0[VERY_LONG_LINE],retw[VERY_LONG_LINE];
  238.     UNIT *cp,*np,*wp;
  239.     int ly,b0;
  240.     int POO =1;    /* minus time flag */
  241.  
  242.     ly = (CWY1-CWY0);
  243.  
  244.     if (!*l) {    /* 長さの無い行と置き換えるのだから、1行削除 */
  245.         line_seigyou();
  246.         wp = xl->ATO;
  247.         line_deleten_echo(xl->MAE,xl->ATO);
  248.         if (CL == xl) {    /* xl が CL だった */
  249.             CL = wp;
  250.         }
  251.         kflag = string_2unit_check(wp->MAE,wp->ATO);
  252.         return(kflag);
  253.     }
  254.  
  255.     if ((wp = xl->MAE) && (wp != HEAD)) {        /* 前の実体がある */
  256.  
  257.         switch(etc_sign(kflag = string_unit_line_check(wp,l))) {
  258.             UBYTE w[VERY_LONG_LINE * 2],w2[VERY_LONG_LINE * 2];
  259. /* - = 前へ送った、0 = 送り無し、+ = 後ろへ送った */
  260. /* 送ったバイト数を返す */
  261.                             /* やり取りがある */
  262.  
  263.         case 1:        /* 後ろに送った */
  264.             line_get_body(w2,wp);
  265.             cut_2line_link_check(w2,l,w,l,CURRENT_JIZUME);
  266.             line_store_and_echo(wp,w);
  267.             break;
  268.         case -1:    /* 前に送った */
  269.                 /* CL が消えている可能性がある */
  270.             line_get_body(w2,wp);
  271.             cut_2line_link_check(w2,l,w,l,CURRENT_JIZUME);
  272.             line_store_and_echo(wp,w);
  273.  
  274.              if (!*l) {    /* 長さの無い行と置き換えるのだから、1行削除 */
  275.                 line_seigyou();
  276.                 wp = xl->ATO;
  277.                 line_deleten_echo(xl->MAE,xl->ATO);
  278.                 if (CL == xl) {    /* wp が CL だった */
  279. /*                    CL = HEAD->ATO;*/
  280.                     CL = wp;
  281.                 }
  282. /*                kflag = string_2unit_check(xl->MAE,xl->ATO);*/
  283.                 return(kflag);
  284.             }
  285.             break;
  286.         case 0:        /* やり取りが無い */
  287.             break;    /* 何もしない */
  288.         }
  289.     }
  290.     cp = xl;
  291.     while((y < ly) || (POO)) {/* !!!!!! */
  292.         if ((np = cp->ATO) == TAIL){
  293.                 /* 最後の行であるから l だけで複数行作って終わり */
  294.             cut_line(l,retw,l,CURRENT_JIZUME);
  295.             line_store_and_echo(cp,retw);
  296.             while(*l) {
  297.                 cut_line(l,retw,l,CURRENT_JIZUME);
  298.                 wp = line_get_free_and_store(retw);
  299.                 line_append1_echo(wp);
  300.             }
  301.             return(kflag);
  302.         }
  303.         line_get_body(w0,np);    /* w0 は常にその次の行の中身を示す */
  304. /*sysflag = 1;*/
  305.         flag = cut_2line_link_check(l,w0,retw,l,CURRENT_JIZUME);
  306.         switch (etc_sign(flag)) {
  307.         case 0:        /* 出入りが無かった */
  308.             line_store_and_echo(cp,retw);
  309.             return(kflag);    /* 終わり */
  310.  
  311.         case -1:    /* 前に送られた */
  312.             if (etc_last(retw) == CR) {    /* retw の終わりは改行 */
  313.                 line_seigyou();
  314.                     /* 一行削除:ただしその行は袋の後ろにあること */
  315.                 line_delete1_echo_after_bag(np);
  316.                 line_store_and_echo(cp,retw);
  317.                 return(kflag);    /* 終わり */
  318.             }
  319.             if (!*l) {    /* 短過ぎたかも? */
  320.                 strcpy(l,retw);    /* 戻す */
  321.                 np = np->ATO;
  322.                 line_delete1_echo_after_bag(np->MAE);
  323.                 if (np == TAIL) {
  324.                     line_store_and_echo(cp,l);
  325.                     break;
  326.                 }
  327.                 line_cat_body(l,np);    /* その次の行を取って来る */
  328.                 line_delete1_echo_after_bag(np);
  329.                 break;
  330.             }
  331.             /* retw で1行作って良い */
  332.             line_store_and_echo(cp,retw);
  333.             cp = cp->ATO;
  334.             break;
  335.         case 1:        /* 後ろに送った */
  336.                 /* retw で1行作って良い */
  337.             line_store_and_echo(cp,retw);
  338.             cp = cp->ATO;
  339.             break;
  340.         default:
  341.             error("バグです3");
  342.             break;
  343.         }
  344.         y++;
  345. /*
  346.         if (cp == SCREEN[CWY1]) {
  347. etc_beep();etc_beep();etc_beep();POO = 0;
  348.         }
  349. */
  350.     }
  351. /*
  352.     if (y != ly) {
  353.         error("バグです4");
  354.     }
  355. */
  356.     np = cp->ATO;
  357.     line_empty_bag(w0);        /* 最下行なら袋から持ってくる */
  358.     flag = cut_2line_link_check(l,w0,retw,l,CURRENT_JIZUME);
  359.     switch (etc_sign(flag)) {
  360.     case 0:        /* 出入りが無かった */
  361.     case 1:        /* 後ろに送った */
  362.         line_store_and_echo(cp,retw);
  363.         line_to_bag(l);    /* 袋に戻す */
  364.         break;
  365.  
  366.     case -1:    /* 前に送った */
  367.         if (!*l && (etc_jlast(retw) != CR)) {
  368.                 /* 短過ぎた可能性がある、もしくはちょうどぴったり */
  369.             if (np == TAIL) {    /* 次の行はない */
  370.                 line_store_and_echo(cp,retw);
  371.                 line_to_bag(l);    /* 袋に戻す */
  372.                 break;
  373.             }
  374.             strcpy(l,retw);        /* 戻す */
  375.             line_get_body(w0,np);
  376.             /* その次の行=画面外の最初の行の中身を取って来る */
  377.             line_delete1_echo_after_bag(np); /* すぐ外の行を削除 */
  378.             cut_2line_link_check(l,w0,retw,l,CURRENT_JIZUME);
  379.             line_store_and_echo(cp,retw);
  380.             line_to_bag(l);    /* 残りを袋に入れる */
  381.             break;
  382.         } else {
  383.             line_store_and_echo(cp,retw);
  384.             line_to_bag(l);    /* 残りを袋に入れる */
  385.             break;
  386.         }
  387.     default:
  388.         error("バグです5");
  389.         break;
  390.     }
  391.     return(kflag);
  392. }
  393.  
  394.  
  395. /* CPX の位置にカーソルを表示する */
  396. void
  397. work_cursor_cpx()
  398. {
  399.     if (TBUFFC || TBUFFC_R) {
  400.         window_loc(TX,TY);
  401.     } else {
  402.         window_loc(CX = ANALYZE[CPX].XPOS,CY);
  403.     }
  404. }
  405.  
  406. /* CPX の位置にカーソルを表示する */
  407. void
  408. work_cursor_cpx0()
  409. {
  410.     window_loc(CX = ANALYZE[CPX].XPOS,CY);
  411. }
  412.  
  413. /* CX0 に最も近い CPX を返す */
  414. int
  415. work_CX0_to_CPX(int cx00)
  416. {
  417.     register int i = 0;
  418.     register int x;
  419.  
  420.     if (!cx00) {    /* 0なら0 */
  421.         return(0);
  422.     }
  423.     while(1) {
  424.         x = ANALYZE[i].XPOS;
  425.         if (x > cx00) return(i-1);        /* 行き過ぎた */
  426.         if (x == cx00) {            /* 一致した */
  427.             if (line_cl_1byte(i-1) == CR) {    /* 左が改行 */
  428.                 i--;
  429.             }
  430.             return(i);
  431.         }
  432.         if (i && (x == 0)) {        /* 行が短い */
  433.             if (line_cl_1byte(--i-1) == CR) {    /* 左が改行 */
  434.                 i--;
  435.             }
  436.             return(i);
  437.         }
  438.         i++;
  439.     }
  440. }
  441.  
  442. /* CL の b バイト目に当る CPX を返す */
  443. int
  444. work_byte_to_CPX(int b)
  445. {
  446.     register int i = 0;
  447.     register int bp;
  448.  
  449.     while(1) {
  450.         bp = ANALYZE[i].BPOS;
  451.         if (bp > b) return(i-1);    /* 行き過ぎた */
  452.         if (bp == b) return(i);        /* 一致した */
  453.         i++;
  454.     }
  455. }
  456.  
  457. int get_buff_c;
  458. UBYTE beta0[VERY_LONG_LINE * 2],gamma0[VERY_LONG_LINE * 2];
  459.  
  460. /* αとのやり取りを考慮しつつ、β+カットバッファ+γを、整行したカットバッファリストにする */
  461. /* -1 = 空、さもなくば、CUT_BUFF の総バイト長を返す */
  462. /* αが NULL ならやり取りのチェックはしない */
  463. /* αとのやり取りがたったなら、αそのものの長さを代えて戻す */
  464. int
  465. work_make_cut_buff0_list(STR alpha,STR beta,STR gamma)
  466. {
  467.     int c = 0,c0 = 0,tbl;
  468.  
  469.     under_print((STR)"カットバッファリスト作成中…");
  470.     line_deleten_list(CUT_BUFF_HEAD0,CUT_BUFF_TAIL0);
  471.     CUT_BUFF_HEAD0 = CUT_BUFF_TAIL0 = NIL;
  472.     get_buff_c = -1;
  473.     strcpy(beta0,beta);
  474.     strcpy(gamma0,gamma);
  475.  
  476.     *l = EOS;
  477.     tbl = -(strlen(beta) + strlen(gamma));    /* 最初の長さ */
  478.     c = work_get_buff(l);    /* 最初の1行を取って来る */
  479.     tbl += c;
  480.     if (c && alpha) {    /* 何か持ってきた */
  481.         /* 十分に長い1行を取ってきたのだから、alpha とのやり取りは判定可能 */
  482.         /* いきなり切る */
  483.         cut_2line_link_check(alpha,l,alpha,l,CURRENT_JIZUME);
  484.     }
  485.     while(1) {
  486.         cut_line(l,s,l,CURRENT_JIZUME);
  487.         if ((strlen(l) > 0) || (etc_last(s) == CR)) {    /* s にはしっかり1行ある */
  488.             work_append_cut_buff0_list(s);
  489.             continue;        /* 続行 */
  490.         } else {        /* s にしっかり1行ある保証がない */
  491.             strcpy(l,s);        /* 戻す */
  492.             c = work_get_buff(l);    /* 取って来る(追加) */
  493.             tbl += c;
  494.             if (!c) {        /* もう無い */
  495.                 if (*l) {    /* 1行にはならないが何かある */
  496.                     work_append_cut_buff0_list(l);
  497.                 }
  498.                 under_blanc();
  499.                 return(tbl);
  500.             } else {        /* 取ってこれた */
  501.                 continue;
  502.             }
  503.         }
  504.     }
  505. }
  506.  
  507. UNIT *
  508. work_append_cut_buff0_list(UBYTE *s)
  509. {
  510.     UNIT *p;
  511.     
  512.     if (!(p = line_get_free_and_store(s))) return(NIL);
  513.  
  514.     if (CUT_BUFF_HEAD0) {            /* 整行されたカットバッファリストがある */
  515.         CUT_BUFF_TAIL0->ATO = p;    /* 最後の次が手持ちになる */
  516.         p->MAE = CUT_BUFF_TAIL0;    /* 手持ちの前は最後 */
  517.         p->ATO = NIL;            /* 新しい最後は NIL を指す */
  518.         CUT_BUFF_TAIL0 = p;        /* 新しい最後を指す */
  519.     } else {            /* フリーラインがない */
  520.         CUT_BUFF_HEAD0 = CUT_BUFF_TAIL0 = p;
  521.         p->MAE = p->ATO = NIL;
  522.     }
  523.     return(p);
  524. }
  525.  
  526. /* beta0 + カットバッファリスト + gamma0 から文字列を返して行く(追加) */
  527. /* 長さを返す */
  528. /* 長さが0ならもう無いということ */
  529. /* カウンタを初期化してから使う必要あり */
  530. int
  531. work_get_buff(STR d)
  532. {
  533.     int len,c;
  534.     UBYTE w[VERY_LONG_LINE];
  535.  
  536.     if (get_buff_c == -1) {
  537.         get_buff_c = 0;
  538.         strcat(d,beta0);
  539.         len = strlen(beta0);
  540.     } else {
  541.         len = 0;
  542.     }
  543.  
  544.     while(string_disp_len(d) < CURRENT_JIZUME+6) {
  545.         c = buff_get_from_cut_buff(w,0,get_buff_c);
  546.             /* カットバッファより1行取ってくる */
  547.         if (c < 0) {    /* もうない */
  548.             strcat(d,gamma0);
  549.             len += strlen(gamma0);
  550.             *gamma0 = EOS;
  551.             return(len);
  552.         }
  553.         get_buff_c = c + 1;
  554.         strcat(d,w);
  555.         len += strlen(w);
  556.     }
  557.     return(len);
  558. }
  559.  
  560. /* 整行されたカットバッファリストの頭から順番に1つづつ外して行く */
  561. UNIT *
  562. work_get_from_cut_buff0_list()
  563. {
  564.     UNIT *wp;
  565.  
  566.     if (wp = CUT_BUFF_HEAD0) {
  567.         CUT_BUFF_HEAD0 = CUT_BUFF_HEAD0->ATO;
  568.     }    /* HEAD が NIL なら TAIL は無効だからこれでいいのだ */
  569.     return(wp);
  570. }
  571.  
  572. /* CL が指している行(CL_DATA)の解析 */
  573. void
  574. work_line_analyze()
  575. {
  576.     register int i = 1;
  577.     int bc = 0;
  578.     int xc;
  579.  
  580.     xc = 0;
  581.     ANALYZE[0].BPOS = ANALYZE[0].XPOS = 0;
  582.     if (CL) {
  583.         do {
  584.             bc = line_touch_next_char(bc,&xc);
  585.             ANALYZE[i].BPOS = bc;
  586.             ANALYZE[i++].XPOS = xc;
  587.         } while(CL_DATA[bc]);
  588.         ANALYZE[i].BPOS = bc+1;
  589.         ANALYZE[i].XPOS = 0;    /* 最後を納めて終わり */
  590.     } else {
  591.         error("バグです。奇妙な行を処理しました");
  592.     }
  593. }
  594.  
  595.  
  596. /* 2つの指定行の指定バイト位置の間を、s で置き換える */
  597. /* len < 0 なら、文字列の長さでトレースする */
  598. /* さもなくば len でトレースする */
  599. /* 画面にエコーする */
  600. void
  601. work_replace_str_echo(UNIT *p1,int bp1,UNIT *p2,int bp2,STR s,int len,int yy)
  602. {
  603.     int ccc;
  604.     UBYTE w[VERY_LONG_LINE*4];
  605.     int bb,ll;
  606.     register UNIT *wp,*wp0;
  607.  
  608.     if (len < 0) {
  609.         len = strlen(s);
  610.     }
  611.     line_get_body(l,p1);
  612.     strcpy(&l[bp1],s);
  613.     line_get_body(w,p2);
  614.     strcat(&l[bp1],&w[bp2]);
  615.     if (((wp = p1) != p2) && (p2 != TAIL)){
  616.         line_deleten_echo(p1,p2->ATO);
  617.     }
  618.     work_xl_replace_minus_xxx(p1,yy);
  619.     if ((p1->MAE != HEAD) && ((ccc = string_2unit_check(p1->MAE,p1)) < 0)) {/* 前へ送った:rare case! */
  620.         line_get_body(l,p1);
  621.         line_cat_body(l,p1->ATO);
  622.         line_store(p1->ATO,"");
  623.         work_xl_replace_minus(p1,bp1+len);
  624.         if ((len+ccc) < 0) {    /* カーソルは前の行に移動する */
  625.             CL = CL->MAE;
  626.             bb = (len += CL->LENGTH);
  627. #if 0
  628.     etc_beep();
  629.             if (--CY < 0) {    /* 上にはみ出た */
  630.     etc_beep();etc_beep();
  631.             }
  632. #endif
  633.         } else {    /* カーソルは p1(+len) の上にある */
  634.                 /* カーソルのある行は(前へは)移動しない */
  635.             len += ccc;
  636.             if (!len) {    /* 前の行に送られ、自分は行頭にいる */
  637.                 if (CL == TAIL) {
  638.                     UNIT *wp;
  639.  
  640.                     /* 前の行は一行で完結しており、CL はその先にある */
  641.                     wp = line_get_free_and_store("");
  642.                     line_append1_echo(wp);
  643.                     disp_1line_rel(window_is_this_line_in_current(wp),wp);
  644.                     CL = line_trace_byte(wp,0,len,&bb,&ll);
  645.                 } else {
  646.                     bb = 0;
  647.                 }
  648.             } else {
  649.                 CL = line_trace_byte(p1,bp1,len,&bb,&ll);
  650.                 CY = yy + ll;    /* CY は画面上 */
  651.             }
  652.         }
  653.     } else {        /* 禁則処理にともなう出し入れは無かった */
  654.         CL = line_trace_byte(p1,bp1,len,&bb,&ll);
  655.         CY = yy + ll;    /* CY は画面上 */
  656.     }
  657. /*=================================*/
  658.     line_cl_cl();
  659.     work_line_analyze();
  660.     CPX = work_byte_to_CPX(bb);
  661.     CX0 = CX = ANALYZE[CPX].XPOS;
  662.     if (CPX && (line_cl_1byte(CPX-1) == CR)) {    /* 左が改行 */
  663.         if (CL->ATO == TAIL) {
  664.             ctrl_b();
  665.         } else {
  666.             ctrl_f();
  667.         }
  668.     }
  669. }
  670.  
  671. /* 2つの指定行の指定バイト位置の間を、s で置き換える */
  672. /* 画面にエコーする */
  673. /* トレースしない */
  674. /* CL とは関係なく実行出来る */
  675. int
  676. work_replace_str_echo_xxx(UNIT *p1,int bp1,UNIT *p2,int bp2,STR s)
  677. {
  678.     UBYTE w[VERY_LONG_LINE*4];
  679.     int bb,ll;
  680.     register UNIT *wp,*wp0;
  681.     int flag;
  682.  
  683.     jump(p1,bp1);        /* CL = p1,line_cl_cl() を実行する */
  684.     line_get_body(l,p1);    /* 行を読み出す */
  685.     strcpy(&l[bp1],s);    /* 置き換え部分を持ってくる */
  686.     line_get_body(w,p2);    /* 行を読み出す */
  687.     strcat(&l[bp1],&w[bp2]);
  688.     if (((wp = p1) != p2) && (p2 != TAIL)){
  689.         line_deleten_echo(p1,p2->ATO);
  690.         flag = 1;
  691.     } else {
  692.         flag = 0;
  693.     }
  694.     work_xl_replace_minus_xxx(p1,CY);
  695.     return(flag);
  696. }
  697.  
  698.  
  699.  
  700. /* 現在のカーソル位置に1バイトコードを挿入する:エコーする */
  701. void
  702. work_insert1(UBYTE c)
  703. {
  704.     register int i;
  705.  
  706.     if ((FP_MODE[3] == 'H') &&        /* 変換モード */
  707.         (!(!TBUFFC && ((c == 13)||(c == 10)||(c == TAB)||(c == ' '))))) {/* (もしくは、最初に改行、タブ)でない */
  708.         int nx,ny;
  709.  
  710.         if (TBUFFC) {        /* 未確定入力追加 */
  711.             xf_append_tb(c);
  712.         } else {        /* 未確定入力開始 */
  713.             TTOPL00 = line_my_top();
  714.             TL00 = TL1 = TL0 = CL;    /* 変換バッファの開始行 */
  715.             CRX = CRY = 0;
  716.             TPX00 = TPX0 = CPX;
  717.             TX00 = TX = TX0 = CX;
  718.             TY00 = TY = TY0 = CY;
  719.             TBP1 = TBP00 = TBP0 = ANALYZE[CPX].BPOS;
  720.             xf_append_tb(c);
  721.         }
  722.     } else {
  723.  
  724. /*
  725. if (sysflag) {
  726. window0();
  727. printf("\n(%d)(%d)[%s]\n",CPX,ANALYZE[CPX].BPOS,CL_DATA);
  728. binkey();
  729. }
  730. */
  731.         line_cl_strncpy(l,i = ANALYZE[CPX].BPOS);    /* ok */
  732.         l[i] = c;
  733.         l[i+1] = EOS;
  734.         line_cl_strcat(l,i);                /* ok */
  735.         work_cl_replace_plus(i+1);
  736. /*
  737. window0();
  738. printf("\n(%d)(%d)[%s]\n",CPX,ANALYZE[CPX].BPOS,CL_DATA);
  739. binkey();
  740. sysflag = 1;
  741. */
  742.     }
  743. }
  744.  
  745. /* 現在のカーソル位置に2バイトコードを挿入する:エコーする */
  746. void
  747. work_insert2(UINT c)
  748. {
  749.     register int i;
  750.  
  751.     if ((FP_MODE[3] == 'H') &&    /* 変換モード */
  752.         (!(!TBUFFC && (c == 0x8140)))) {/* (もしくは、最初に空白)でない */
  753.         int nx,ny;
  754.  
  755.         if (TBUFFC) {        /* 未確定入力追加 */
  756.             xf_append_tb(c);
  757.         } else {        /* 未確定入力開始 */
  758.             TTOPL00 = line_my_top();
  759.             TL00 = TL1 = TL0 = CL;    /* 変換バッファの開始行 */
  760.             CRX = CRY = 0;
  761.             TPX00 = TPX0 = CPX;
  762.             TX00 = TX = TX0 = CX;
  763.             TY00 = TY = TY0 = CY;
  764.             TBP1 = TBP00 = TBP0 = ANALYZE[CPX].BPOS;
  765.             xf_append_tb(c);
  766.         }
  767.         xf_init_tb_r0();
  768.     } else {
  769.         UINT cd;
  770.  
  771.         if ((c == L'゜') && (cd = etc_handakuten_able()) || ((c == L'゛') && (cd = etc_dakuten_able()))) {
  772.             /* YES なら既に ctrl_b してある */
  773.             ctrl_d();
  774.             c = cd;
  775.         }
  776.         line_cl_strncpy(l,i = ANALYZE[CPX].BPOS);    /* ok */
  777.         l[i] = (UBYTE) (c >> 8);
  778.         l[i+1] = (UBYTE) (c & 0xff);
  779.         l[i+2] = EOS;
  780.         line_cl_strcat(l,i);                /* ok */
  781.         work_cl_replace_plus(i+2);
  782.         if (TBUFFC_R) {        /* 未確定ローマ字を表示 */
  783.             xf_init_tb00();
  784.             TTOPL00 = line_my_top();
  785.             TL00 = TL1 = TL0 = CL;    /* 変換バッファの開始行 */
  786.             CRX = CRY = 0;
  787.             TPX00 = TPX0 = CPX;
  788.             TX00 = TX = TX0 = CX;
  789.             TY00 = TY = TY0 = CY;
  790.             TBP1 = TBP00 = TBP0 = ANALYZE[CPX].BPOS;
  791.             xf_disp_insert(&TX,&TY);
  792.         }
  793.     }
  794. }
  795.  
  796. /* 指定された行を l に置き換える。画面全体にエコーする */
  797. /* y は行座標 */
  798. /* 禁則処理の関係で、前の行へ送り込まれたら非零を返す */
  799. /* 前の行に何バイト送り込まれたかを返す */
  800. int
  801. work_xl_replace_minus_xxx(UNIT *xl,int y)
  802. {
  803.     int flag,kflag = 0;
  804.     UBYTE w0[VERY_LONG_LINE],retw[VERY_LONG_LINE];
  805.     UNIT *cp,*np,*wp;
  806.     int ly,b0;
  807.  
  808.     ly = (CWY1-CWY0);
  809.  
  810.     cp = xl;
  811.     while(y < ly) {
  812.         if ((np = cp->ATO) == TAIL) {
  813.             /* 最後の行であるから l だけで複数行作って終わり */
  814.             cut_line(l,retw,l,CURRENT_JIZUME);
  815.             line_store_and_echo(cp,retw);
  816. /*            line_delete1_echo_after_bag(cp);*/
  817. /*            wp = line_get_free_and_store(retw);*/
  818. /*            line_append1_echo(wp);*/
  819.             y++;
  820.             while(*l) {
  821.                 cut_line(l,retw,l,CURRENT_JIZUME);
  822.                 wp = line_get_free_and_store(retw);
  823.                 line_append1_echo(wp);
  824.                 y++;
  825.             }
  826.             if (y < ly) {
  827.                 disp_middle_flush(y,TAIL);
  828.             }
  829.             return(kflag);
  830.         }
  831.         line_get_body(w0,np);    /* w0 は常にその次の行の中身を示す */
  832.  
  833.         flag = cut_2line_link_check(l,w0,retw,l,CURRENT_JIZUME);
  834.         switch (etc_sign(flag)) {
  835.         case 0:        /* 出入りが無かった */
  836.             line_store_and_echo(cp,retw);
  837.             if (++y < ly) {
  838.                 disp_middle_flush(y,cp->ATO);
  839.             }
  840.             return(kflag);    /* 終わり */
  841.  
  842.         case -1:    /* 前に送られた */
  843.             if (etc_last(retw) == CR) {    /* retw の終わりは改行 */
  844.                 line_seigyou();
  845.                     /* 一行削除:ただしその行は袋の後ろにあること */
  846.                 line_delete1_echo_after_bag(np);
  847.                 line_store_and_echo(cp,retw);
  848.                 if (++y < ly) {
  849.                     disp_middle_flush(y,cp->ATO);
  850.                 }
  851.                 return(kflag);    /* 終わり */
  852.             }
  853.             if (!*l) {    /* 短過ぎた */
  854.                 strcpy(l,retw);    /* 戻す */
  855.                 np = np->ATO;
  856.                 line_delete1_echo_after_bag(np->MAE);
  857.                 if (np == TAIL) {
  858. /*                    wp = line_get_free_and_store(l);*/
  859. /*error("-12");*/
  860.                     line_store_and_echo(cp,l);
  861. /*                    line_delete1_echo_after_bag(TAIL->MAE);*/
  862.                     break;
  863.                 }
  864.                 line_cat_body(l,np);    /* その次の行を取って来る */
  865.                 line_delete1_echo_after_bag(np);
  866. /*                cp = cp->ATO;*/        /* loop top で np 更新 */
  867.                 break;
  868.  
  869.             }
  870.             /* retw で1行作って良い */
  871.             line_store_and_echo(cp,retw);
  872.             cp = cp->ATO;
  873.             break;
  874.         case 1:        /* 後ろに送った */
  875.                 /* retw で1行作って良い */
  876. /*            line_store(cp,retw);*/
  877.             line_store_and_echo(cp,retw);
  878. /*window0();printf("(%s)[%x][%x]",retw,cp,cp->ATO);binkey();*/
  879.             cp = cp->ATO;
  880.             break;
  881.         default:
  882.             error("バグです6");
  883.             break;
  884.         }
  885.         y++;
  886.     }
  887.     if (y != ly) {
  888.         error("バグです7");
  889.     }
  890.     np = cp->ATO;
  891.     line_empty_bag(w0);        /* 最下行なら袋から持ってくる */
  892.     flag = cut_2line_link_check(l,w0,retw,l,CURRENT_JIZUME);
  893.     switch (etc_sign(flag)) {
  894.     case 0:        /* 出入りが無かった */
  895.     case 1:        /* 後ろに送った */
  896.         line_store_and_echo(cp,retw);
  897.         line_to_bag(l);    /* 袋に戻す */
  898.         break;
  899.  
  900.     case -1:    /* 前に送った */
  901.         if (!*l) {    /* 短過ぎた */
  902.             if (np == TAIL) {    /* 次の行はない */
  903.                 line_store_and_echo(cp,retw);
  904.                 line_to_bag(l);    /* 袋に戻す */
  905.                 break;
  906.             }
  907.             strcpy(l,retw);        /* 戻す */
  908.             line_get_body(w0,np);    /* その次の行を取って来る */
  909.             line_delete1_echo_after_bag(np); /* すぐ外の行を削除 */
  910.             cut_2line_link_check(l,w0,retw,l,CURRENT_JIZUME);
  911.             line_store_and_echo(cp,retw);
  912.             line_to_bag(l);    /* 残りを袋に入れる */
  913.             break;
  914.         } else {
  915.             line_store_and_echo(cp,retw);
  916.             line_to_bag(l);    /* 残りを袋に入れる */
  917.             break;
  918.         }
  919.     default:
  920.         error("バグです8");
  921.         break;
  922.     }
  923.     return(kflag);
  924. }
  925.  
  926. /* 2点間を削除してカットバッファに入れる */
  927. /* 削除した中にマークがあったなら、マークを移動、取り除いてカットバッファに入れる */
  928. /* 2つユニットへのポインタと、バイト位置を与える */
  929. void
  930. work_delete_to_cut_buff_xxx(UNIT *p1,int b1,UNIT *p2,int b2)
  931. {
  932.     work_delete_to_cut_buff0(p1,b1,p2,b2,0);
  933. }
  934.  
  935. /* 2点間を削除してカットバッファに入れる */
  936. /* 削除した中にマークがあったなら、マークを移動、取り除いてカットバッファに入れる */
  937. /* 2つユニットへのポインタと、バイト位置を与える */
  938. void
  939. work_delete_to_cut_buff(UNIT *p1,int b1,UNIT *p2,int b2)
  940. {
  941.     work_delete_to_cut_buff0(p1,b1,p2,b2,1);
  942. }
  943.  
  944. /* 2点間を削除してカットバッファに入れる */
  945. /* 削除した中にマークがあったなら、マークを移動、取り除いてカットバッファに入れる */
  946. /* 2つユニットへのポインタと、バイト位置を与える */
  947. void
  948. work_delete_to_cut_buff0(UNIT *p1,int b1,UNIT *p2,int b2,int flag)
  949. {
  950.     UBYTE wl[VERY_LONG_LINE*4];
  951.  
  952.     if (etc_line_order(&p1,&b1,&p2,&b2)) {    /* 勝手に入れ替えてくれる */
  953.         if (p1 == p2) {    /* 同じ行であった */
  954.             work_delete_between(p1,b1,b2,flag);    /* その行の一部を削除 */
  955.             line_get_body(l,p1);    /* 行の内容を取り出す */
  956.             CL = p1;        /* 現在行はその行 */
  957.             if (CL->ATO != TAIL) {
  958.                 line_cat_body(l,CL->ATO);
  959.                 line_delete1_echo_after_bag(CL->ATO);
  960.             }
  961.             work_cl_replace_plus(b1);
  962.         } else {
  963.             UNIT *wp,*wp0;
  964.             int w;
  965.  
  966.             work_delete_between(p1,b1,line_length(p1),flag);
  967.             line_get_body(wl,p1);
  968.             wp = p1->ATO;
  969.             while(wp != p2) {
  970.                 work_delete_between(wp,0,line_length(wp),flag);
  971.                 line_cat_body(wl,wp);
  972.                 wp = wp->ATO;
  973.             }
  974. /* wl の中には残りの文字列とマークの両方が入っている */
  975.             work_delete_between(p2,0,b2,flag);
  976.             strcpy(l,wl);
  977.             line_cat_body(l,p2);
  978.             line_deleten_echo(p1,p2->ATO);
  979.             CL = p1;
  980.             CY = window_is_this_line_in_current(CL);
  981. /*
  982. window0();
  983. printf("[%s]",l);binkey();
  984. */
  985.             work_cl_replace_plus(b1);
  986.             disp_cl_y(CY);
  987.         }
  988.     } else {
  989.         error("バグです9");
  990.     }
  991. }
  992.  
  993. /* 2点間をカットバッファに入れる */
  994. /* 削除した中にマークがあったなら、当然取り除いてカットバッファに入れる */
  995. /* 2つユニットへのポインタと、バイト位置を与える */
  996. void
  997. work_copy_to_cut_buff(UNIT *p1,int b1,UNIT *p2,int b2)
  998. {
  999.     if (etc_line_order(&p1,&b1,&p2,&b2)) {    /* 勝手に入れ替えてくれる */
  1000.         if (p1 == p2) {    /* 同じ行であった */
  1001.             work_copy_to_cut_buff_1line(p1,b1,b2);
  1002.         } else {
  1003.             UNIT *wp;
  1004.  
  1005.             work_copy_to_cut_buff_1line(p1,b1,line_length(p1));
  1006.             wp = p1->ATO;
  1007.             while(wp != p2) {
  1008.                 work_copy_to_cut_buff_1line(wp,0,line_length(wp));
  1009.                 wp = wp->ATO;
  1010.             }
  1011.             work_copy_to_cut_buff_1line(p2,0,b2);
  1012.         }
  1013.     } else {
  1014.         error("バグです10");
  1015.     }
  1016. }
  1017.  
  1018. /* 一行の2点間をカットバッファに入れる */
  1019. /* 削除した中にマークがあったなら、当然取り除いてカットバッファに入れる */
  1020. /* ユニットへのポインタと、バイト位置を与える */
  1021. void
  1022. work_copy_to_cut_buff_1line(UNIT *p,int b1,int b2)
  1023. {
  1024.     register int i;
  1025.  
  1026.     line_get_body(w,p);
  1027.     strncpy(s,&w[b1],b2-b1);
  1028.     s[b2-b1] = EOS;
  1029.     buff_add_to_cut_buff(s);
  1030. }
  1031.  
  1032. /* 現在のカーソル位置に1バイトコードを挿入する:カーソルは進めない */
  1033. /* エコーする */
  1034. void
  1035. work_insert1_right(UBYTE c)
  1036. {
  1037.     register int i;
  1038.  
  1039.     line_cl_strncpy(l,i = ANALYZE[CPX].BPOS);    /* ok */
  1040.     l[i] = c;
  1041.     l[i+1] = EOS;
  1042.     line_cl_strcat(l,i);                /* ok */
  1043.     work_cl_replace_minus();
  1044. }
  1045.  
  1046. void
  1047. work_set_underline(UNIT *p1,int b1,UNIT *p2,int b2)
  1048. {
  1049.     register UNIT *wp;
  1050.     register int be;
  1051.  
  1052.     if (etc_line_order(&p1,&b1,&p2,&b2)) {    /* 勝手に入れ替えてくれる */
  1053.         while(1) {
  1054.             if (p1 == p2) {    /* 同じ行であった */
  1055.                 /* b1,b2 の間にアンダーラインコードを埋め込んで終了 */
  1056.                 work_set_underline1(p1,b1,b2);
  1057.                 if (b1 != b2) {
  1058.                     change_check();
  1059.                 }
  1060.                 ctrl_l();
  1061.                 break;
  1062.             } else {    /* (p1,b1)-(p1,last) にコードを埋め込む */
  1063.                 work_set_underline1(p1,b1,be = line_length(p1));
  1064.                 if (b1 != be) {
  1065.                     change_check();
  1066.                 }
  1067.             }
  1068.             p1 = p1->ATO;
  1069.             b1 = 0;
  1070.         }
  1071.     } else {
  1072.         error("バグです11");
  1073.     }
  1074. }
  1075.  
  1076. /* p1 の b1 から b2 までにアンダーラインを挿入する */
  1077. void
  1078. work_set_underline1(UNIT *p1,int b1,int b2)
  1079. {
  1080.     UBYTE l[VERY_LONG_LINE],s[VERY_LONG_LINE];
  1081.     register int count,bc,bc0;
  1082.     int dummy;
  1083.     register UBYTE *p;
  1084.  
  1085.     line_get_body(l,p1);
  1086.     count = bc = b1;
  1087.     strncpy(s,l,count);
  1088.  
  1089.     while(bc < b2) {
  1090.         /* p[bc] から始めて、次の文字までのバイト数を返す */
  1091.         /* *xc から表示しているとして、*xc を更新する */
  1092.         bc = line_touch_next_char_x(l,bc0 = bc,&dummy);    /* 次の実体までのカウント */
  1093.              /* ^実体を越える */
  1094.  
  1095.         p = string_search_xcode(&l[bc0]);        /* 最初の XCODE の位置 */
  1096.         while(1) {
  1097. /*
  1098. window0();
  1099. printf("{p=%x}{bc=%x}{bc0=%x}\n",p,bc,bc0);
  1100. printf("[bc]=%x}{[bc0]=%x}\n",l[bc],l[bc0]);binkey();
  1101. */
  1102.             if (*line_skip_xcode(&l[bc0]) == CR) {
  1103.                 /* 改行にアンダーラインはつかない */
  1104.                 break;
  1105.             }
  1106.  
  1107.             if ((!p) || ((UINT)p >= (UINT)&l[bc])) {
  1108.                     /* 無い or もっと先 */
  1109.                 s[count++] = XCODE_UP;
  1110.                 s[count++] = XCODE_UL;
  1111.                 break;
  1112.             } else {
  1113.                 if (*(++p) == XCODE_UL) {    /* 既にアンダーラインがあった */
  1114.                     break;            /* 何もしないで抜ける */
  1115.                 }
  1116.                 p = string_search_xcode(p);    /* 次の XCODE の位置 */
  1117.             }
  1118.         }
  1119.         strncpy(&s[count],&l[bc0],bc-bc0);
  1120.         count += bc-bc0;
  1121.     }
  1122.     if (l[bc]) {
  1123.         int ll;
  1124.  
  1125.         ll = strlen(&l[bc]);
  1126.         strncpy(&s[count],&l[bc],ll);
  1127.         s[count+ll] = EOS;
  1128.     } else {
  1129.         s[count] = EOS;
  1130.     }
  1131.     line_store(p1,s);
  1132. }
  1133.  
  1134. void
  1135. work_erase_underline(UNIT *p1,int b1,UNIT *p2,int b2)
  1136. {
  1137.     register UNIT *wp;
  1138.     register int be;
  1139.  
  1140.     if (etc_line_order(&p1,&b1,&p2,&b2)) {    /* 勝手に入れ替えてくれる */
  1141.         while(1) {
  1142.             if (p1 == p2) {    /* 同じ行であった */
  1143.                 /* b1,b2 の間にアンダーラインコードを消去して終了 */
  1144.                 work_erase_underline1(p1,b1,b2);
  1145.                 if (b1 != b2) {
  1146.                     change_check();
  1147.                 }
  1148.                 ctrl_l();
  1149.                 break;
  1150.             } else {    /* (p1,b1)-(p1,last) のコードを消去 */
  1151.                 work_erase_underline1(p1,b1,be = line_length(p1));
  1152.                 if (b1 != be) {
  1153.                     change_check();
  1154.                 }
  1155.             }
  1156.             p1 = p1->ATO;
  1157.             b1 = 0;
  1158.         }
  1159.     } else {
  1160.         error("バグです12");
  1161.     }
  1162. }
  1163.  
  1164. /* p1 の b1 から b2 までのアンダーラインを消去する */
  1165. void
  1166. work_erase_underline1(UNIT *p1,int b1,int b2)
  1167. {
  1168.     UBYTE l[VERY_LONG_LINE],s[VERY_LONG_LINE];
  1169.     register int count,bc;
  1170.  
  1171.     line_get_body(l,p1);
  1172.     count = bc = b1;
  1173.     strncpy(s,l,count);
  1174.  
  1175.     while(bc < b2) {
  1176.         if ((l[bc] == XCODE_UP) && (l[bc+1] == XCODE_UL)) {
  1177.             bc += 2;
  1178.             continue;
  1179.         }
  1180.         s[count++] = l[bc++];
  1181.     }
  1182.  
  1183.     if (l[bc]) {
  1184.         int ll;
  1185.  
  1186.         ll = strlen(&l[bc]);
  1187.         strncpy(&s[count],&l[bc],ll);
  1188.         s[count+ll] = EOS;
  1189.     } else {
  1190.         s[count] = EOS;
  1191.     }
  1192.     line_store(p1,s);
  1193. }
  1194.  
  1195.